iT邦幫忙

2021 iThome 鐵人賽

DAY 21
0
Software Development

iOS 學習筆記系列 第 21

Day21 URLSession 01 - POST

  • 分享至 

  • xImage
  •  

URLSession

前言:
我們在開發專案時常常需要跟網路上的後台(Server)溝通互動,這就必須用到網路請求,我們會發送 request 給 Server,Server 會再回傳 response來串接網路上Server 的API,而 iOS 在 iOS 9 之後使用NSURLSession實現網路請求,透過NSURLSessionURLSession物件建立一個請求Task,然後執行Task 即可,包括快取、多執行緒任務等 iOS 都已經在sdk 層面封裝完畢

以下我們就來看看如何使用URLSession串接 RESTful API,我們用Reqres API 來示範,串接API 會使用到的Data Model 可以參考Codable JSON 教學

POST:建立資料

首先我們根據以上的Request Body 以及Response 建立關於Post Sample 的Model

User.swift

struct UserRequestBody: Encodable {
    var name: String
    var job: String
}

struct UserPostResponse: Decodable {
    var name: String
    var job: String
    var id: String?
    var dateCreated: Date?
    
    var modifiedId: String {
        if let newId = id {
            return newId
        } else {
            return "******"
        }
    }
    
    var modifiedDateCreated: String {
        let dateFormatter = DateFormatter()
        dateFormatter.dateStyle = .medium
        if let newDate = dateCreated {
            return dateFormatter.string(from: newDate)
        } else {
            return "******"
        }
    }
    
    enum CodingKeys: String, CodingKey {
        case name
        case job
        case id
        case dateCreated = "createdAt"
    }
}

接著建立UserURLSession.swift來處理關於URLSession的事件

import Foundation

class UserURLSession {
    static let shared = UserURLSession()
    
    func userPostRequest(userRequestBody:UserRequestBody,completionHandler: @escaping (UserPostResponse) -> Void) {
        
        let url = URL(string: "https://reqres.in/api/users")!
        
        // MARK: URLRequest
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        
        guard let httpBody = try? JSONEncoder().encode(userRequestBody) else {
            print("Invalid httpBody")
            return
        }
        
        // MARK: Set httpBody
        request.httpBody = httpBody
        
        URLSession.shared.dataTask(with: request) {
            data, response, error in
            if let data = data {
                do {
                    let decoder = JSONDecoder()
                    
                    decoder.dateDecodingStrategy = .formatted(DateFormatter.customFormatter)
                    
                    let user = try decoder.decode(UserPostResponse.self, from: data)
                    
                    completionHandler(user)
                    
                }catch(let error) {
                    print(error.localizedDescription)
                }
            } else {
                print("No Data")
            }
        }.resume()
    }
}

extension DateFormatter {
    static let customFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
        formatter.calendar = Calendar(identifier: .iso8601)
        formatter.timeZone = TimeZone(secondsFromGMT: 0)
        formatter.locale = Locale(identifier: "en_us_POSIX")
        return formatter
    }()
}

之後在View 設計畫面並使用

POSTSampleView.swift

struct POSTSampleView: View {
    
    @State private var name = "Ryder"
    @State private var job = "Engineer"
    
    @State var user :UserPostResponse = UserPostResponse(name: "*****", job: "*****", id: nil, dateCreated: nil)
    
    var body: some View {
        NavigationView {
            VStack {
                List(){
                    Text("POST sample")
                    Section(header: Text("Request Data")) {
                        TextField("Name: ", text: $name)
                        TextField("Job: ", text: $job)
                    }
                }
                List() {
                    Section(header: Text("Response Data")) {
                        Text("Name: \(user.name)")
                        Text("Job: \(user.job)")
                        Text("ID: \(user.modifiedId)")
                        Text("Date created: \(user.modifiedDateCreated)")
                    }
                }
                .listStyle(GroupedListStyle())
                Button {
                    UserURLSession.shared.userPostRequest(userRequestBody: UserRequestBody(name: name, job: job)) { newUser in
                        DispatchQueue.main.async {
                            user = newUser
                        }
                    }
                    
                } label: {
                    Text("POST Request")
                }
                .padding()
                .foregroundColor(Color.white)
                .background(Color.green)
                .cornerRadius(8)
                
            }            
            .navigationBarTitleDisplayMode(.inline)
            .navigationTitle(Text("URLSession POST Sample"))
        }
        
    }
}

struct POSTSampleView_Previews: PreviewProvider {
    static var previews: some View {
        POSTSampleView()
    }
}

這邊所有URLSession 的範例一起放在Github: URLSessionSample 供大家參考


上一篇
Day20 Combine 07 - Operators 其他常用操作符
下一篇
Day22 URLSession 02 - GET
系列文
iOS 學習筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言